package xyz.xtt.pay.service.order;

import static xyz.xtt.common.asset.AssertUtils.isFalse;
import static xyz.xtt.common.asset.AssertUtils.isNull;
import static xyz.xtt.common.asset.AssertUtils.isTrue;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.api.enums.BizTypeEnum;
import xyz.xtt.asset.api.enums.GoodsTypeEnum;
import xyz.xtt.asset.api.enums.SellPatternEnum;
import xyz.xtt.asset.client.response.AssetAccountResponse;
import xyz.xtt.asset.client.response.AssetInfoResponse;
import xyz.xtt.asset.client.response.AssetStaticResponse;
import xyz.xtt.pay.api.enums.PayOrderBusinessTypeEnum;
import xyz.xtt.pay.api.enums.PayOrderStatusEnum;
import xyz.xtt.pay.client.request.MakeOrderRequest;
import xyz.xtt.pay.constants.ErrorMessage;
import xyz.xtt.pay.entity.TblBusinessOrder;
import xyz.xtt.pay.service.BusinessOrderOperator;
import xyz.xtt.pay.service.IInnerService;
import xyz.xtt.pay.service.INftOrderService;
import xyz.xtt.pay.service.ITblBusinessOrderService;

/**
 * 拥有实物的NFT购买订单操作（目前只有亚姐盲盒）
 * 
 * @author dale
 * @date 2025/3/18
 **/
@Service
@Slf4j
public class PhysicalNftPurchaseBusinessOrderOperator implements BusinessOrderOperator {
	@Autowired
	private INftOrderService nftOrderService;
	@Autowired
	private ITblBusinessOrderService iTblBusinessOrderService;
	@Autowired
	private IInnerService iInnerService;

	/**
	 * 是否支持该类型的订单
	 *
	 * @param type
	 * @return
	 */
	@Override
	public boolean canOperateType(PayOrderBusinessTypeEnum type) {
		return Objects.equals(type, PayOrderBusinessTypeEnum.ASSET_WITH_PHYSICAL);
	}

	/**
	 * 创建订单
	 *
	 * @param uid              用户ID
	 * @param makeOrderRequest 创建订单请求
	 * @return 订单
	 */
	@Override
	public TblBusinessOrder makeOrder(String uid, MakeOrderRequest makeOrderRequest) {
		long assetAccountId = Long.parseLong(makeOrderRequest.getAssetAccountId());
		int purchaseAmount = makeOrderRequest.getPurchaseAmount();
		isTrue(purchaseAmount > 1, ErrorMessage.INVALID_QUANTITY);
		long buyerId = Long.parseLong(uid);
		long receiveAddressId = Long.parseLong(makeOrderRequest.getReceiveAddressId());
		AssetAccountResponse assetAccount = iInnerService.accountInfoWithId(assetAccountId);
		isNull(assetAccount, ErrorMessage.ASSET_ACCOUNT_NOT_EXIST);
		isFalse(assetAccount.getAmount().intValue() >= purchaseAmount, ErrorMessage.STOCK_NOT_ENOUGH);
		isTrue(Objects.equals(buyerId, assetAccount.getOwnerId()), ErrorMessage.CAN_NOT_BUY_SELF);
		long sellerId = assetAccount.getOwnerId();
		AssetInfoResponse asset = iInnerService.infoWithAssetId(assetAccount.getAssetId());
		isNull(asset, ErrorMessage.ASSET_NOT_EXIST);
		isFalse(Objects.equals(BizTypeEnum.NFT.dbType(), asset.getBizType()), ErrorMessage.ASSET_STATUS_EX);
		isFalse(Objects.equals(asset.getSellable(), 1), ErrorMessage.ASSET_NOT_SELLABLE);
		isFalse(Objects.equals(asset.getSellPattern(), SellPatternEnum.BUY_NOW_PRICE.code()), ErrorMessage.ASSET_STATUS_EX);
		AssetStaticResponse assetStaticResource = iInnerService.staticInfoWithAssetId(assetAccount.getAssetId());
		isNull(assetStaticResource, ErrorMessage.ASSET_STATUS_EX);

		GoodsTypeEnum goodsTypeEnum = GoodsTypeEnum.valueOf(PayOrderBusinessTypeEnum.ASSET_WITH_PHYSICAL.name());
		// 检查是否有待支付的订单
		TblBusinessOrder unPayOrder = iTblBusinessOrderService.getUnPayBusinessOrder(buyerId, goodsTypeEnum.getCode(), String.valueOf(asset.getId()));
		if (unPayOrder != null) {
			return unPayOrder;
		}

		BigDecimal unitPrice = assetAccount.getPrice();
		// 测试用户重置单价
		unitPrice = nftOrderService.testUserResetPrice(buyerId, unitPrice);
		TblBusinessOrder businessOrder = buildBusinessOrder(asset, assetStaticResource, unitPrice, sellerId, buyerId, PayOrderBusinessTypeEnum.ASSET_WITH_PHYSICAL, purchaseAmount, unitPrice);
		businessOrder.setReceiveAddressId(receiveAddressId);
		isFalse(iTblBusinessOrderService
				.save(businessOrder), ErrorMessage.ORDER_CREATE_FAILED, () -> log.error("save order failed. order:{}", JSONUtil.toJsonStr(businessOrder)));
		return businessOrder;
	}

	private TblBusinessOrder buildBusinessOrder(AssetInfoResponse asset, AssetStaticResponse assetStaticResource, BigDecimal unitPrice, long sellerId,
			long buyerId, PayOrderBusinessTypeEnum businessTypeEnum, int purchaseAmount, BigDecimal price) {
		TblBusinessOrder order = new TblBusinessOrder();
		order.setOrderId(IdUtil.getSnowflakeNextId());
		order.setGoodsId(String.valueOf(asset.getId()));
		order.setGoodsType(GoodsTypeEnum.valueOf(businessTypeEnum.name()).getCode());
		order.setGoodsName(asset.getAssetName());
		order.setGoodsImage(assetStaticResource.getLogoUri());
		order.setSellerId(sellerId);
		order.setAppUserId(buyerId);
		order.setPurchaseNum(purchaseAmount);
		order.setOriginPrice(unitPrice.setScale(2, RoundingMode.HALF_UP));
		order.setRealPrice(order.getOriginPrice());
		order.setTransportPrice(BigDecimal.ZERO);
		order.setDiscountAmount(BigDecimal.ZERO);
		order.setTotalPrice(calculateOrderTotalPrice(order));
		order.setPayAmount(order.getTotalPrice());
		order.setOrderStatus(PayOrderStatusEnum.UN_PAY.getCode());
		LocalDateTime now = LocalDateTime.now();
		order.setOrderTime(now);
		order.setCreateTime(now);
		order.setUpdateTime(now);
		return order;
	}

}
